package com.ruoyi.service;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.flowable.*;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.dto.*;
import com.ruoyi.entity.SysForm;
import com.ruoyi.vo.DispatchTasksVO;
import com.ruoyi.vo.FlowTaskVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.dynamic.DynamicUserTaskBuilder;
import org.flowable.engine.impl.persistence.entity.HistoricActivityInstanceEntity;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLinkInfo;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author XuanXuan
 *
 **/
@Service
@Slf4j
public class FlowTaskServiceImpl extends FlowServiceFactory {

    @Resource
    private SysUserServiceImpl sysUserService;


    @Resource
    private SysRoleServiceImpl sysRoleService;


    @Resource
    private SysDeployFormServiceImpl sysInstanceFormService;

    /**
     * 完成任务
     *
     * @param taskVo 请求实体参数
     */
    public AjaxResult complete(FlowTaskVO taskVo) {
        Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
        if (Objects.isNull(task)) {
            return AjaxResult.error("任务不存在");
        }
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
        taskService.setVariable(taskVo.getTaskId(), "lastAuditUserId", sysUser.getUserId()+"");
        taskService.setVariable(taskVo.getTaskId(), "candidatesUserId", taskVo.getCandidatesUserId());
        taskService.setVariable(taskVo.getTaskId(), "lastDeptCode", sysUser.getDept().getOrgNo());

        if (DelegationState.PENDING.equals(task.getDelegationState())) {
            taskService.addComment(taskVo.getTaskId(), task.getProcessInstanceId(), FlowComment.DELEGATE.getCode(), taskVo.getComment());
            taskService.resolveTask(taskVo.getTaskId(), taskVo.getValues());
        } else {
            String nickname = sysUser.getNickName();
            String comment = String.format("%s 审批通过 %s", nickname, StringUtils.isEmpty(taskVo.getComment()) ? "" : "， 批示：" + taskVo.getComment());
            taskService.addComment(taskVo.getTaskId(), task.getProcessInstanceId(), FlowComment.NORMAL.getCode(), comment);
            Long userId = sysUser.getUserId();
            identityService.setAuthenticatedUserId(userId.toString());
            taskService.setAssignee(taskVo.getTaskId(), userId.toString());
            taskService.complete(taskVo.getTaskId(), taskVo.getValues());
        }
        return AjaxResult.success();
    }

    private SysUser getCompleteUser(Task task) {
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        String assignee = task.getAssignee();
        List<String> links = historyService.getHistoricIdentityLinksForTask(task.getId()).stream().map(IdentityLinkInfo::getUserId).collect(Collectors.toList());
        if (NumberUtil.isNumber(assignee)) {
            return sysUserService.getById(Long.valueOf(assignee));
        } else if (links.size() >= 1) {
            return sysUserService.getById(links.get(0));
        } else {
            return loginUser;
        }
    }

    /**
     * 驳回任务
     *
     * @param flowTaskVo
     */

    public void taskReject(FlowTaskVO flowTaskVo) {
        if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
            throw new ServiceException("任务处于挂起状态!");
        }
        // 当前任务 task
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        taskService.setVariable(flowTaskVo.getTaskId(), "lastAuditUserId", sysUser.getUserId()+"");
        taskService.setVariable(flowTaskVo.getTaskId(), "candidatesUserId", flowTaskVo.getCandidatesUserId());
        taskService.setVariable(flowTaskVo.getTaskId(), "lastDeptCode", sysUser.getDept().getOrgNo());
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        taskService.addComment(flowTaskVo.getTaskId(), task.getProcessInstanceId(), FlowComment.STOP.getCode(), "驳回，意见：" + flowTaskVo.getComment());
        stopProcessInstanceById(task.getProcessInstanceId());

    }

    public void stopProcessInstanceById(String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance != null) {
            //1、获取终止节点
            List<EndEvent> endNodes =findEndFlowElement(processInstance.getProcessDefinitionId());
            String endId = endNodes.get(0).getId();
            //2、执行终止
            List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
            List<String> executionIds = new ArrayList<>();
            executions.forEach(execution -> executionIds.add(execution.getId()));

            runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState();
            log.info("终止processInstanceId:{}成功",processInstanceId);
        }else {
            log.info("不存在运行的流程实例processInstanceId:{},请确认!",processInstanceId);
        }
    }

    public List findEndFlowElement(String processDefId) {
        Process mainProcess = repositoryService.getBpmnModel(processDefId).getMainProcess();
        Collection<FlowElement> list = mainProcess.getFlowElements();
        if (CollectionUtils.isEmpty(list)) {
            return Collections.EMPTY_LIST;
        }
        return list.stream().filter(f -> f instanceof EndEvent).collect(Collectors.toList());
    }

    /**
     * 退回任务
     *
     * @param flowTaskVo 请求实体参数
     */
    @Transactional(rollbackFor = Exception.class)

    public void taskReturn(FlowTaskVO flowTaskVo) {
        if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
            throw new ServiceException("任务处于挂起状态");
        }
        // 当前任务 task
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        // 获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
        // 获取所有节点信息
        Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
        // 获取全部节点列表，包含子节点
        Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
        // 获取当前任务节点元素
        FlowElement source = null;
        // 获取跳转的节点元素
        FlowElement target = null;
        if (allElements != null) {
            for (FlowElement flowElement : allElements) {
                // 当前任务节点元素
                if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
                    source = flowElement;
                }
                // 跳转的节点元素
                if (flowElement.getId().equals(flowTaskVo.getTargetKey())) {
                    target = flowElement;
                }
            }
        }

        // 从当前节点向前扫描
        // 如果存在路线上不存在目标节点，说明目标节点是在网关上或非同一路线上，不可跳转
        // 否则目标节点相对于当前节点，属于串行

        // 获取所有正常进行的任务节点 Key，这些任务不能直接使用，需要找出其中需要撤回的任务
        List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
        List<String> runTaskKeyList = new ArrayList<>();
        runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
        // 需退回任务列表
        List<String> currentIds = new ArrayList<>();
        // 通过父级网关的出口连线，结合 runTaskList 比对，获取需要撤回的任务
        List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
        currentUserTaskList.forEach(item -> currentIds.add(item.getId()));

        // 循环获取那些需要被撤回的节点的ID，用来设置驳回原因
        List<String> currentTaskIds = new ArrayList<>();
        currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
            if (currentId.equals(runTask.getTaskDefinitionKey())) {
                currentTaskIds.add(runTask.getId());
            }
        }));
        // 设置回退意见
        //SysUser user = SecurityUtils.getLoginUser().getUser();
        SysUser user = getCompleteUser(task);

        String nickname = user.getNickName();
        String comment = String.format("%s 退回 %s", nickname, StringUtils.isEmpty(flowTaskVo.getComment()) ? "" : "， 批示：" + flowTaskVo.getComment());
        identityService.setAuthenticatedUserId(user.getUserId().toString());
        currentTaskIds.forEach(currentTaskId -> {
            taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getCode(), comment);
            taskService.setAssignee(task.getId(), user.getUserId().toString());
        });

        try {
            // 1 对 1 或 多 对 1 情况，currentIds 当前要跳转的节点列表(1或多)，targetKey 跳转到的节点(1)
            runtimeService.createChangeActivityStateBuilder()
                    .processInstanceId(task.getProcessInstanceId())
                    .moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState();
        } catch (FlowableObjectNotFoundException e) {
            throw new ServiceException("未找到流程实例，流程可能已发生变化");
        } catch (FlowableException e) {
            throw new ServiceException("无法取消或开始活动");
        }
    }


    /**
     * 获取所有可回退的节点
     *
     * @param flowTaskVo
     * @return
     */

    public AjaxResult findReturnTaskList(FlowTaskVO flowTaskVo) {
        // 当前任务 task
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        List<FlowViewerDTO> flowViewerList = getFlowViewer(task.getProcessInstanceId(), null);

        // 获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
        // 获取所有节点信息，暂不考虑子流程情况
        Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
        Collection<FlowElement> flowElements = process.getFlowElements();

        // 获取当前任务节点元素
        UserTask source = null;
        if (flowElements != null) {
            for (FlowElement flowElement : flowElements) {
                // 类型为用户节点
                if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
                    source = (UserTask) flowElement;
                }
            }
        }
        // 获取节点的所有路线
        List<List<UserTask>> roads = FlowableUtils.findRoad(source, null, null, null);
        // 可回退的节点列表
        List<UserTask> userTaskList = new ArrayList<>();
        for (List<UserTask> road : roads) {
            if (userTaskList.size() == 0) {
                // 还没有可回退节点直接添加
                userTaskList = road;
            } else {
                // 如果已有回退节点，则比对取交集部分
                userTaskList.retainAll(road);
            }
        }

        List<UserTask> userTaskList2 = new ArrayList<>();
        for (int i = 0; i < userTaskList.size(); i++) {
            UserTask userTask = userTaskList.get(i);
            long count = flowViewerList.stream().filter(r -> r.getKey().equals(userTask.getId()) && r.getCompleted()).count();
            if (count > 0) {
                userTaskList2.add(userTask);
            }
        }
        List<HistoricActivityInstance> nodeList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .orderByHistoricActivityInstanceStartTime()
                .desc().list();
        userTaskList2.sort(new Comparator<UserTask>() {

            public int compare(UserTask o1, UserTask o2) {
                HistoricActivityInstance activityInstance1 = nodeList.stream().filter(n -> n.getActivityId().equals(o1.getId())).findAny().orElse(null);
                HistoricActivityInstance activityInstance2 = nodeList.stream().filter(n -> n.getActivityId().equals(o2.getId())).findAny().orElse(null);
                return (int) (activityInstance1.getStartTime().getTime() - activityInstance2.getStartTime().getTime());
            }
        });
        return AjaxResult.success(userTaskList2);
    }

    /**
     * 删除任务
     *
     * @param flowTaskVo 请求实体参数
     */

    public void deleteTask(FlowTaskVO flowTaskVo) {
        // todo 待确认删除任务是物理删除任务 还是逻辑删除，让这个任务直接通过？
        taskService.deleteTask(flowTaskVo.getTaskId(), flowTaskVo.getComment());
    }

    /**
     * 认领/签收任务
     *
     * @param flowTaskVo 请求实体参数
     */

    @Transactional(rollbackFor = Exception.class)
    public void claim(FlowTaskVO flowTaskVo) {
        taskService.claim(flowTaskVo.getTaskId(), flowTaskVo.getUserId());
    }

    /**
     * 取消认领/签收任务
     *
     * @param flowTaskVo 请求实体参数
     */

    @Transactional(rollbackFor = Exception.class)
    public void unClaim(FlowTaskVO flowTaskVo) {
        taskService.unclaim(flowTaskVo.getTaskId());
    }

    /**
     * 委派任务
     *
     * @param flowTaskVo 请求实体参数
     */

    @Transactional(rollbackFor = Exception.class)
    public void delegateTask(FlowTaskVO flowTaskVo) {
        taskService.delegateTask(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
    }


    /**
     * 转办任务
     *
     * @param flowTaskVo 请求实体参数
     */

    @Transactional(rollbackFor = Exception.class)
    public void assignTask(FlowTaskVO flowTaskVo) {
        taskService.setAssignee(flowTaskVo.getTaskId(), flowTaskVo.getComment());
    }

    /**
     * 我发起的流程
     *
     * @return
     */

    public List<FlowTaskDTO> myProcess(String name, String usersId) {
        List<FlowTaskDTO> list = actHiProcinstMapper.getMyProcess(usersId, name);
        list.stream().forEach(row -> {
            long time = row.getFinishTime().getTime() - row.getCreateTime().getTime();
            row.setDuration(getDate(time));
        });
        return list;
    }

    /**
     * 取消申请
     *
     * @param flowTaskVo
     * @return
     */

    public AjaxResult stopProcess(FlowTaskVO flowTaskVo) {
        List<Task> task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).list();

        if (CollectionUtils.isEmpty(task)) {
            throw new ServiceException("流程不在运行中");
        }
        // 获取当前需撤回的流程实例
        ProcessInstance processInstance =
                runtimeService.createProcessInstanceQuery()
                        .processInstanceId(flowTaskVo.getInstanceId())
                        .singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        if (Objects.nonNull(bpmnModel)) {
            Process process = bpmnModel.getMainProcess();
            List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
            if (CollectionUtils.isNotEmpty(endNodes)) {
                SysUser loginUser = SecurityUtils.getLoginUser().getUser();
                Authentication.setAuthenticatedUserId(loginUser.getUserId().toString());
                taskService.addComment(null, processInstance.getProcessInstanceId(), FlowComment.STOP.getCode(),
                        StringUtils.isBlank(flowTaskVo.getComment()) ? String.format("%s终止了申请", loginUser.getNickName()) : String.format("%s终止了申请,批示：", loginUser.getNickName(), flowTaskVo.getComment()));
                // 获取当前流程最后一个节点
                String endId = endNodes.get(0).getId();
                List<Execution> executions =
                        runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
                List<String> executionIds = executions.stream().map(Execution::getId).collect(Collectors.toList());
                // 变更流程为已结束状态
                runtimeService.createChangeActivityStateBuilder()
                        .moveExecutionsToSingleActivityId(executionIds, endId).changeState();
            }
        }

        return AjaxResult.success();
    }

    /**
     * 撤回流程  目前存在错误
     *
     * @param flowTaskVo
     * @return
     */

    public AjaxResult revokeProcess(FlowTaskVO flowTaskVo) {
        Task task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult();
        if (task == null) {
            throw new ServiceException("流程未启动或已执行完成，无法撤回");
        }

        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .orderByTaskCreateTime()
                .asc()
                .list();
        String myTaskId = null;
        HistoricTaskInstance myTask = null;
        for (HistoricTaskInstance hti : htiList) {
            if (loginUser.getUserId().toString().equals(hti.getAssignee())) {
                myTaskId = hti.getId();
                myTask = hti;
                break;
            }
        }
        if (null == myTaskId) {
            throw new ServiceException("该任务非当前用户提交，无法撤回");
        }

        String processDefinitionId = myTask.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

        //变量
//      Map<String, VariableInstance> variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
        String myActivityId = null;
        List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
                .executionId(myTask.getExecutionId()).finished().list();
        for (HistoricActivityInstance hai : haiList) {
            if (myTaskId.equals(hai.getTaskId())) {
                myActivityId = hai.getActivityId();
                break;
            }
        }
        FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);

        Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
        FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);

        //记录原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<>(flowNode.getOutgoingFlows());


        return AjaxResult.success();
    }


    /**
     * 代办任务列表
     *
     * @param name
     * @param deployTime
     * @return
     */
    public List<FlowTaskDTO> todoList(String name, String deployTime, String limit, String usersId) {

        Map param = new HashMap();
        param.put("usersId", usersId);
        param.put("name", name);
        param.put("deployTime", deployTime);
        param.put("limit", limit);

        List<FlowTaskDTO> list = actHiProcinstMapper.getTodoList(param);
        list.stream().forEach(row -> {
            row.setIsStartUser(usersId.contains(row.getStartUserId() + "") ? "true" : "false");
        });
        return list;
    }


    /**
     * 已办任务列表
     *
     * @return
     */

    public List<FlowTaskDTO> finishedList(String name, String usersId) {
        Map param = new HashMap();
        param.put("usersId", usersId);
        param.put("name", name);
        List<FlowTaskDTO> list = actHiProcinstMapper.finishedList(param);
        for (FlowTaskDTO flowTask : list) {
            // 审批人员信息
            long time = flowTask.getFinishTime().getTime() - flowTask.getCreateTime().getTime();
            flowTask.setDuration(getDate(time));
        }
        return list;
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    /**
     * 流程历史流转记录
     *
     * @param procInsId 流程实例Id
     * @return
     */

    public Map<String, Object> flowRecord(String procInsId, String deployId) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(procInsId)) {
            List<HistoricActivityInstance> list = historyService
                    .createHistoricActivityInstanceQuery()
                    .processInstanceId(procInsId)
                    .orderByHistoricActivityInstanceStartTime()
                    .desc().list();
            List<FlowTaskDTO> hisFlowList = new ArrayList<>();
            for (HistoricActivityInstance histIns : list) {
                if (StringUtils.isNotBlank(histIns.getTaskId())) {
                    FlowTaskDTO flowTask = new FlowTaskDTO();
                    flowTask.setTaskId(histIns.getTaskId());
                    flowTask.setTaskName(histIns.getActivityName());
                    flowTask.setCreateTime(histIns.getStartTime());
                    flowTask.setFinishTime(histIns.getEndTime());
                    if (!StrUtil.isNullOrUndefined(histIns.getAssignee())) {
                        SysUser sysUser = sysUserService.selectUserById(Long.parseLong(histIns.getAssignee()));
                        flowTask.setAssigneeId(sysUser.getUserId());
                        flowTask.setAssigneeName(sysUser.getNickName());
                        flowTask.setDeptName(sysUser.getDept().getDeptName());
                    }
                    // 展示审批人员
                    List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId());
                    StringBuilder stringBuilder = new StringBuilder();
                    for (HistoricIdentityLink identityLink : linksForTask) {
                        // 获选人,候选组/角色(多个)
                        if ("candidate".equals(identityLink.getType())) {
                            if (StringUtils.isNotBlank(identityLink.getUserId()) && !"null".equals(identityLink.getUserId())) {
                                SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
                                stringBuilder.append(sysUser.getNickName()).append(",");
                            }
                            if (StringUtils.isNotBlank(identityLink.getGroupId())) {
                                SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
                                stringBuilder.append(sysRole.getRoleName()).append(",");
                            }
                        }
                    }
                    if (StringUtils.isNotBlank(stringBuilder)) {
                        flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
                    }

                    flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis()));
                    // 获取意见评论内容
                    List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId());
                    commentList.forEach(comment -> {
                        if (histIns.getTaskId().equals(comment.getTaskId())) {
                            flowTask.setFlowStatus(comment.getType());
                            flowTask.setComment(FlowCommentDTO.builder().type(comment.getType()).comment(comment.getFullMessage()).build());
                        }
                    });
                    hisFlowList.add(flowTask);
                }
            }
            List<Comment> commentList = taskService.getProcessInstanceComments(procInsId);
            List<Comment> otherCommentList = commentList.stream().filter(r -> r.getTaskId() == null).collect(Collectors.toList());
            otherCommentList.stream().forEach(row -> {
                FlowTaskDTO flowTask = new FlowTaskDTO();
                flowTask.setFlowStatus(row.getType());
                flowTask.setComment(FlowCommentDTO.builder().type(row.getType()).comment(row.getFullMessage()).build());
                flowTask.setFinishTime(row.getTime());

                hisFlowList.add(0, flowTask);
            });
            map.put("flowList", hisFlowList);
//            // 查询当前任务是否完成
//            List<Task> taskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
//            if (CollectionUtils.isNotEmpty(taskList)) {
//                map.put("finished", true);
//            } else {
//                map.put("finished", false);
//            }
        }
        // 第一次申请获取初始化表单
        if (StringUtils.isBlank(procInsId)) {
            SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId);
            if (Objects.isNull(sysForm)) {
                map.put("formData", new HashMap<>());
            } else {
                map.put("formData", JSONObject.parseObject(sysForm.getFormContent()));
            }

        }
        return map;
    }

    /**
     * 根据任务ID查询挂载的表单信息
     *
     * @param taskId 任务Id
     * @return
     */

    public Task getTaskForm(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        return task;
    }

    /**
     * 获取流程过程图
     *
     * @param processId
     * @return
     */

    public InputStream diagram(String processId) {
        String processDefinitionId;
        // 获取当前的流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        // 如果流程已经结束，则得到结束节点
        if (Objects.isNull(processInstance)) {
            HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();

            processDefinitionId = pi.getProcessDefinitionId();
        } else {// 如果流程没有结束，则取当前活动节点
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        }

        // 获得活动的节点
        List<HistoricActivityInstance> highLightedFlowList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();

        List<String> highLightedFlows = new ArrayList<>();
        List<String> highLightedNodes = new ArrayList<>();
        //高亮线
        for (HistoricActivityInstance tempActivity : highLightedFlowList) {
            if ("sequenceFlow".equals(tempActivity.getActivityType())) {
                //高亮线
                highLightedFlows.add(tempActivity.getActivityId());
            } else {
                //高亮节点
                highLightedNodes.add(tempActivity.getActivityId());
            }
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration();

        //获取自定义图片生成器
        ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(),
                configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true);
        return in;

    }

    /**
     * 获取流程执行过程
     *
     * @return
     */
    private void addFlowViewerDto(List<FlowViewerDTO> flowViewerList, HistoricActivityInstance node) {
        if (node.getEndTime() != null) {
            FlowViewerDTO flowViewerDto = new FlowViewerDTO();
            flowViewerDto.setKey(node.getActivityId());
            // 根据流程节点处理时间校验改节点是否已完成
            if (node instanceof HistoricActivityInstanceEntity) {
                HistoricActivityInstanceEntity nodeEntity = (HistoricActivityInstanceEntity) node;
                if (nodeEntity.getDeleteReason() != null && nodeEntity.getDeleteReason().contains("Change activity to")) {
                    flowViewerDto.setCompleted(null);
                } else if (Objects.isNull(nodeEntity.getEndTime())) {
                    flowViewerDto.setCompleted(false);
                } else if (nodeEntity.getActivityType().contains("Flow")) {
                    flowViewerDto.setCompleted(false);
                } else {
                    flowViewerDto.setCompleted(true);
                }
                if (flowViewerDto.getCompleted() != null) {
                    flowViewerList.add(0, flowViewerDto);
                }
            }

        }
    }

    private void addFlowViewerDto(List<FlowViewerDTO> flowViewerList, String key, boolean completed) {
        FlowViewerDTO flowViewerDto = new FlowViewerDTO();
        flowViewerDto.setKey(key);
        flowViewerDto.setCompleted(completed);
        flowViewerList.add(flowViewerDto);
    }

    public List<FlowViewerDTO> getFlowViewer(String procInsId, String executionId) {
        List<FlowViewerDTO> flowViewerList = new ArrayList<>();
        // 获取任务开始节点(临时处理方式)
        List<HistoricActivityInstance> nodeList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(procInsId)
                .orderByHistoricActivityInstanceStartTime()
                .desc().list();
        List<HistoricActivityInstance> flowList = nodeList.stream().filter(row -> "sequenceFlow".equals(row.getActivityType())).collect(Collectors.toList());
        if (nodeList.size() > 0) {

            HistoricActivityInstance lastNode = nodeList.stream().filter(row -> !"sequenceFlow".equals(row.getActivityType())).collect(Collectors.toList()).get(0);
            //1、增加最后一个已完成任务
            addFlowViewerDto(flowViewerList, lastNode);
            BpmnModel bpmnModel = repositoryService.getBpmnModel(lastNode.getProcessDefinitionId());

            String activityId = lastNode.getActivityId();

            //2、向前找其他已完成任务
            findprevNode(bpmnModel, flowList, nodeList, flowViewerList, activityId);

            //3、向后找一个
            List<Task> list = taskService.createTaskQuery().processInstanceId(lastNode.getProcessInstanceId()).active().list();
            list.forEach(row -> {
                FlowViewerDTO flowViewerDto = new FlowViewerDTO();
                flowViewerDto.setKey(row.getTaskDefinitionKey());
                flowViewerDto.setCompleted(false);
                flowViewerList.add(flowViewerDto);
            });
            //4、向后找其他的
            FlowElement flowElement = bpmnModel.getFlowElement(flowViewerList.get(flowViewerList.size() - 1).getKey());
            while (true) {
                if (flowElement instanceof FlowNode) {
                    FlowNode flowNode = (FlowNode) flowElement;
                    if (flowNode.getOutgoingFlows().size() == 0) {
                        break;
                    } else if (flowNode.getOutgoingFlows().size() == 1) {
                        FlowViewerDTO flowViewerDto = new FlowViewerDTO();
                        flowViewerDto.setKey(flowNode.getId());
                        flowViewerDto.setCompleted(false);
                        flowViewerList.add(flowViewerDto);

                        flowElement = flowNode.getOutgoingFlows().get(0).getTargetFlowElement();

                        flowViewerDto = new FlowViewerDTO();
                        flowViewerDto.setKey(flowElement.getId());
                        flowViewerDto.setCompleted(false);
                        flowViewerList.add(flowViewerDto);
                    } else {
                        break;
                    }
                } else if (flowElement instanceof SequenceFlow) {
                    SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
                    flowElement = sequenceFlow.getTargetFlowElement();
                }

            }
        }
        return flowViewerList;
    }

    private void findprevNode(BpmnModel bpmnModel, List<HistoricActivityInstance> flowList, List<HistoricActivityInstance> nodeList, List<FlowViewerDTO> flowViewerList, String activityId) {
        FlowElement flowElement = bpmnModel.getFlowElement(activityId);
        if (!(flowElement instanceof FlowNode)) {
            return;
        }
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(activityId);
        if (flowNode.getIncomingFlows().size() == 0) {
            return;
        }
        List<SequenceFlow> flows = flowNode.getIncomingFlows();
        for (int i = 0; i < flows.size(); i++) {
            SequenceFlow sequenceFlow = flows.get(i);
            findprevNodeByFlow(bpmnModel, flowList, nodeList, flowViewerList, sequenceFlow.getId());
        }
    }

    private void findprevNodeByFlow(BpmnModel bpmnModel, List<HistoricActivityInstance> flowList, List<HistoricActivityInstance> nodeList, List<FlowViewerDTO> flowViewerList, String flowId) {
        FlowElement flowElement = bpmnModel.getFlowElement(flowId);
        if (!(flowElement instanceof SequenceFlow)) {
            return;
        }
        SequenceFlow flow = (SequenceFlow) bpmnModel.getFlowElement(flowId);
        String finalActivityId = flowId;
        if (flowViewerList.stream().filter(r -> r.getKey().equals(finalActivityId)).count() > 0) {
            return;
        }
        flowElement = flow.getSourceFlowElement();
        if (!(flowElement instanceof FlowNode)) {
            return;
        }
        FlowNode flowNode = (FlowNode) flowElement;
        HistoricActivityInstance prevSequ = nodeList.stream().filter(node -> node.getActivityId().equals(flowId)).findAny().orElse(null);
        HistoricActivityInstance prevNode = nodeList.stream().filter(node -> node.getActivityId().equals(flowNode.getId())).findAny().orElse(null);
        if (prevSequ != null) {
            addFlowViewerDto(flowViewerList, prevSequ);
        }
        if (prevNode != null) {
            addFlowViewerDto(flowViewerList, prevNode);
        }
        List<SequenceFlow> sequenceFlowList = flowNode.getIncomingFlows();
        for (int i = 0; i < sequenceFlowList.size(); i++) {
            findprevNodeByFlow(bpmnModel, flowList, nodeList, flowViewerList, sequenceFlowList.get(i).getId());
        }
    }

    /**
     * 获取流程变量
     *
     * @param taskId
     * @param procInsId
     * @return
     */

    public AjaxResult processVariables(String taskId, String procInsId) {
        // 流程变量
        if (!StrUtil.isEmpty(taskId) && taskId.length() > 20) {
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
            if (Objects.nonNull(historicTaskInstance)) {
                return AjaxResult.success(historicTaskInstance.getProcessVariables());
            } else {
                Map<String, Object> variables = taskService.getVariables(taskId);
                return AjaxResult.success(variables);
            }
        } else {
            HistoricProcessInstance historicInstance = historyService.createHistoricProcessInstanceQuery().includeProcessVariables().processInstanceId(procInsId).singleResult();
            if (Objects.nonNull(historicInstance)) {
                return AjaxResult.success(historicInstance.getProcessVariables());
            } else {
                FlowTaskDTO dto = actHiProcinstMapper.getByProcInsId(procInsId);
                Map<String, Object> variables = dto.getVariableMap();
                return AjaxResult.success(variables);
            }
        }

    }

    /**
     * 获取下一节点
     *
     * @param flowTaskVo 任务
     * @return
     */

    public AjaxResult getNextFlowNode(FlowTaskVO flowTaskVo) {
        // Step 1. 获取当前节点并找到下一步节点
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        FlowNextDTO flowNextDto = new FlowNextDTO();
        if (Objects.nonNull(task)) {
            // Step 2. 获取当前流程所有流程变量(网关节点时需要校验表达式)
            Map<String, Object> variables = taskService.getVariables(task.getId());
            List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, variables);
            if (CollectionUtils.isNotEmpty(nextUserTask)) {
                for (UserTask userTask : nextUserTask) {
                    MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics();
                    // 会签节点
                    if (Objects.nonNull(multiInstance)) {
                        List<SysUser> list = sysUserService.selectUserList(new SysUser());

                        flowNextDto.setVars(ProcessConstants.PROCESS_MULTI_INSTANCE_USER);
                        flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
                        flowNextDto.setUserList(list);
                    } else {

                        // 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
                        String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
                        String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);

                        // 处理加载动态指定下一节点接收人员信息
                        if (ProcessConstants.DATA_TYPE.equals(dataType)) {
                            // 指定单个人员
                            if (ProcessConstants.USER_TYPE_ASSIGNEE.equals(userType)) {
                                List<SysUser> list = sysUserService.selectUserList(new SysUser());

                                flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
                                flowNextDto.setType(ProcessConstants.USER_TYPE_ASSIGNEE);
                                flowNextDto.setUserList(list);
                            }
                            // 候选人员(多个)
                            if (ProcessConstants.USER_TYPE_USERS.equals(userType)) {
                                List<SysUser> list = sysUserService.selectUserList(new SysUser());

                                flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
                                flowNextDto.setType(ProcessConstants.USER_TYPE_USERS);
                                flowNextDto.setUserList(list);
                            }
                            // 候选组
                            if (ProcessConstants.USER_TYPE_ROUPS.equals(userType)) {
                                List<SysRole> sysRoles = sysRoleService.selectRoleAll();

                                flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
                                flowNextDto.setType(ProcessConstants.USER_TYPE_ROUPS);
                                flowNextDto.setRoleList(sysRoles);
                            }
                        } else {
                            flowNextDto.setType(ProcessConstants.FIXED);
                        }
                    }
                }
            } else {
                return AjaxResult.success("流程已完结", null);
            }
        }
        return AjaxResult.success(flowNextDto);
    }

    /**
     * 流程完成时间处理
     *
     * @param ms
     * @return
     */
    private String getDate(long ms) {

        long day = ms / (24 * 60 * 60 * 1000);
        long hour = (ms / (60 * 60 * 1000) - day * 24);
        long minute = ((ms / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long second = (ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);

        if (day > 0) {
            return day + "天" + hour + "小时" + minute + "分钟";
        }
        if (hour > 0) {
            return hour + "小时" + minute + "分钟";
        }
        if (minute > 0) {
            return minute + "分钟";
        }
        if (second > 0) {
            return second + "秒";
        } else {
            return 0 + "秒";
        }
    }

    public FlowTaskDTO getByBusinessKey(String key) {
        FlowTaskDTO dto = actHiProcinstMapper.getByBusinessKey(key);
        return dto;
    }


    public void setButtons(Task task, DetailPage page) {
        boolean completeBtn = true;
        boolean isMultipleInstances = false;

        String currTaskKey = task != null ? task.getTaskDefinitionKey() : "";
        if (task == null || !currTaskKey.contains("Activity")) {
            completeBtn = false;
        }
        if (task != null) {
            List<Process> processes = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getProcesses();
            UserTask userTask = FlowableUtils.taskKeyToFlowElement(processes, task.getTaskDefinitionKey());
            isMultipleInstances = userTask.getLoopCharacteristics() != null;
        }
        page.setCompleteBtn(completeBtn);
        page.setReturnBtn(completeBtn && !isMultipleInstances);
        page.setDispatchTaskBtn(currTaskKey.contains("Dispatch"));
        page.setAssignTasksBtn(currTaskKey.equals("AssignTasks"));
        page.setCirculateBtn(currTaskKey.contains("Read"));
        page.setFileSaveBtn(currTaskKey.contains("fileSave"));
        page.setUndertakeBtn(currTaskKey.equals("undertake"));
        page.setUndertakingResultsBtn(currTaskKey.contains("UndertakingResults"));

        page.setDoSendDocumentDistributeBtn(currTaskKey.contains("doSendDocumentDistribute"));//发文分发
        page.setDoSendDocumentPassOnBtn(currTaskKey.contains("doSendDocumentPassOn"));//发文转交

        page.setDoTakeDocumentDistributeBtn(currTaskKey.contains("doTakeDocumentDistribute"));//收文分发
        page.setDoTakeDocumentPassOnBtn(currTaskKey.contains("doTakeDocumentPassOn"));//收文转交


        page.setDoAssignSubordinateOperatorsBtn(currTaskKey.contains("doAssignSubordinateOperators")); //分配下级审批人
        page.setDeputySecretaryBtn(currTaskKey.contains("deputySecretaryBtn")); //是否需要副书记审批
        page.setAssigneeBtn1(currTaskKey.contains("assigneeBtn1") || currTaskKey.contains("setAssigneeBtn1")); //分配下级审批人


    }


    public FlowTaskDTO getByProcInsId(String procInsId, String taskId) {
        FlowTaskDTO dto = actHiProcinstMapper.getByProcInsId(procInsId);
        DetailPage page = new DetailPage();
        if (taskId != null && taskId.length() > 20) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                this.setButtons(task, page);
                //page.setAssigneeBtn1(true);
                dto.setPage(page);

                List<Process> processes = getRepositoryService().getBpmnModel(task.getProcessDefinitionId()).getProcesses();
                dto.setCurrTaskKey(task.getTaskDefinitionKey());
                dto.setFirstNode(task.getTaskDefinitionKey().equals("First"));
                UserTask userTask = FlowableUtils.taskKeyToFlowElement(processes, task.getTaskDefinitionKey());
                dto.setMultipleInstances(userTask.getLoopCharacteristics() != null);
            }
        }
        return dto;
    }

    public String getCurrActivityId(String taskId) {
        Task taskEntity = taskService.createTaskQuery().taskId(taskId).singleResult();
        Assert.isFalse(taskEntity == null, "task:" + taskId + " not found");
        //查找当前节点对应的执行执行实体（感觉兴趣的可以搜下流程执行的实例信息 表为ACT_RU_EXECUTION）
        Execution currentExecutionEntity = runtimeService.createExecutionQuery().executionId(taskEntity.getExecutionId()).singleResult();
        Assert.isFalse(currentExecutionEntity == null, "task:" + taskId + ",execution:" + taskEntity.getExecutionId() + " not found");
        String activityId = currentExecutionEntity.getActivityId();
        return activityId;
    }

    public void doDispatchTasks(DispatchTasksVO dispatchTasksVo) {

        Task task = taskService.createTaskQuery().taskId(dispatchTasksVo.getTaskId()).singleResult();
        String procInsId = task.getProcessInstanceId();
        FlowTaskDTO dto = actHiProcinstMapper.getByProcInsId(procInsId);


        List<String> userIdList = new ArrayList<>(); // TaskCreatedListener.appointorUserTypeToUserListId("user", dispatchTasksVo.getAppointor(), dto.getStartUserId(), procInsId, task.getTaskDefinitionKey());
        Assert.isFalse(userIdList.size() == 0, "请选择处理人");

        //增加审批任务节点
        DynamicUserTaskBuilder handleTaskBuilder = new DynamicUserTaskBuilder();
        String handleTaskId = dispatchTasksVo.getUserTaskId() != null ? dispatchTasksVo.getUserTaskId() + RandomUtil.randomNumbers(5) : "dynamicTask" + RandomUtil.randomNumbers(5);
        handleTaskBuilder.setName(dispatchTasksVo.getNodeName());
        handleTaskBuilder.setId(handleTaskId);
        handleTaskBuilder.setAssignee(CollectionUtil.join(userIdList, ","));

        if (userIdList.size() == 1) {
            managementService.executeCommand(new AfterSignUserTaskCmd(getCurrActivityId(dispatchTasksVo.getTaskId()),
                    procInsId, handleTaskBuilder));
        } else {
            managementService.executeCommand(new AfterMultipleUserTaskCmd(getCurrActivityId(dispatchTasksVo.getTaskId()),
                    procInsId, handleTaskBuilder).setExecutionId(task.getExecutionId()));
        }

        //增加分配任务节点
        DynamicUserTaskBuilder dispatchTaskBuilder = new DynamicUserTaskBuilder();
        dispatchTaskBuilder.setName(task.getName());
        dispatchTaskBuilder.setId("Dispatch" + RandomUtil.randomNumbers(5));
        dispatchTaskBuilder.setAssignee(SecurityUtils.getLoginUser().getUser().getUserId() + "");
        managementService.executeCommand(new AfterSignUserTaskCmd(handleTaskId, procInsId, dispatchTaskBuilder));

        //完成任务
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        identityService.setAuthenticatedUserId(sysUser.getUserId().toString());

        String nickname = SecurityUtils.getLoginUser().getUser().getNickName();
        String comment = String.format("%s 将任务指派给了 %s", nickname, "");
        taskService.addComment(task.getId(), task.getProcessInstanceId(), FlowComment.NORMAL.getCode(), comment);
        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
        taskService.setAssignee(task.getId(), userId.toString());
        taskService.complete(task.getId(), new HashMap<>());
    }


    public AjaxResult completeAndUpdateForm(String taskId, Map<String, Object> variables) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.isNull(task)) {
            return AjaxResult.error("任务不存在");
        }
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
        String nickname = SecurityUtils.getLoginUser().getUser().getNickName();
        String comment = String.format("%s 提交申请%s", nickname, "");
        taskService.addComment(taskId, task.getProcessInstanceId(), FlowComment.NORMAL.getCode(), comment);
        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
        taskService.setAssignee(taskId, userId.toString());
        taskService.complete(taskId, variables);

        FlowTaskDTO dto = actHiProcinstMapper.getByProcInsId(task.getProcessInstanceId());
        //设置流程名称
        SysForm sysForm = sysFormMapper.getByDeployId(dto.getDeployId());
        identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
        variables.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUserId());
        variables.put("formName", sysForm.getFormName());
        String titleFormat = sysForm.getTitleFormat();
        Iterator iterator = variables.keySet().iterator();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            Object val = variables.get(key);
            if (val != null && val != null) {
                titleFormat = titleFormat.replaceAll("\\$" + key, val.toString());
            }
        }
        runtimeService.setProcessInstanceName(task.getProcessInstanceId(), titleFormat);
        return AjaxResult.success();
    }

    /**
     * 判断任务是否完成
     */
    public boolean isTaskCompleted(String procInstId, Long leaderId) {
        if(StrUtil.isBlank(procInstId) || leaderId == null){
            return false;
        }
        //查询flowable 用户是否完成了审批
        // 检查历史任务
        List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(procInstId)
                .taskAssignee(leaderId.toString())
                .list();

        // 检查当前任务
        List<Task> activeTasks = taskService.createTaskQuery()
                .processInstanceId(procInstId)
                .taskAssignee(leaderId.toString())
                .list();

        if (historicTasks.isEmpty() && activeTasks.isEmpty()) {
            return false;
        } else if (!activeTasks.isEmpty()) {
            return false;
        } else {
            return true;
        }
    }
}